/*
 * lcd.c
 *
 *  Created on: Mar 21, 2011
 *      Author: Vishal Verma
 */

#include <at89c51ed2.h>  //also includes 8052.h and 8051.h
#include <mcs51reg.h>
#include <string.h>
#include <stdio.h>
#include "lcd.h"
#include "i2c.h"

//volatile unsigned int *lcdPtr = (unsigned int*)(LCD_ADDR);
xdata at LCD_ADDR volatile unsigned int lcdPtr;

int f_skipBusyChk = TRUE;

/*================================================*/

void init_lcd(void)								 	// Init routine as per HD44780 data sheet
{
	LCD_RS = RS_CMD;								// RS = 0
	LCD_RW = RW_WRITE;								// RW = 0
	delay_millisec(16);                            	// Wait more than 15ms
    wr_lcdReg(0x38);                             	// Initialize for 8 bit , 2 line
    delay_millisec(5);                              // Wait more than 4.1ms
    wr_lcdReg(0x38);
    delay_millisec(1);                             	// Wait more than 0.1ms
    wr_lcdReg(0x38);
    delay_millisec(1);                             	// Wait more than 0.1ms
    wr_lcdReg(0x0C);                             	// Display On; Cursor Off; Blink off
    wr_lcdReg(0x01);                             	// Clear the display
    delay_millisec(5);                            	// Wait more than 1.64ms
    f_skipBusyChk = FALSE;
}

/*================================================*/

void wr_lcdReg(char wrCmd)					 		// Write a command to the LCD.
{
	chkBusy();                                  	// Is the LCD ready to take the command?
    LCD_RS = RS_CMD;                                // Register Select Low for writing command
    LCD_RW = RW_WRITE;                              // R!W low for write
    LCD_PORT = wrCmd;                          		// Command byte to register
    LCD_RS   = RS_CMD;
    LCD_RW   = RW_READ;
}

/*=============================================*/

void wr_lcdDat(char wrData)							// Write a character to the LCD.
{
	chkBusy();                                  	// Is the LCD ready to take the command?
    LCD_RS = RS_DATA;                               // Register Select High for writing data
    LCD_RW = RW_WRITE;                              // R!W low for write
    LCD_PORT = wrData;                            	// Data byte to data port
    LCD_RS   = RS_CMD;
    LCD_RW   = RW_READ;
}

/*==============================================*/

void chkBusy(void) {

	volatile unsigned char rdCmd = 0;

	if (FALSE == f_skipBusyChk) {
		P0 = 0xFF ;                                  	// Set port as input
		LCD_RS   = RS_CMD;
		LCD_RW   = RW_READ;

	/*	do {
			//rdCmd = LCD_PORT;
			if (LCD_PORT & 0x80 == 0x00) {
				break;
			}
			TESTPIN ? (TESTPIN = 0) : (TESTPIN = 1);
			NOP;
			TESTPIN ? (TESTPIN = 0) : (TESTPIN = 1);
			NOP;
		//}while (lcdPtr & 0x80 != 0x00);
		}while (P0 & 0x80 != 0x00);
	*/

		do {
			rdCmd = lcdPtr;
		}while (rdCmd & 0x80);
	}
}

/*=============================================*/

void lcdgotoaddr (unsigned char addr) {

	if(addr < 0x80) {
		chkBusy();
		wr_lcdReg(LCDHOME | addr);
	}
}

/*=============================================*/

void lcdgotoxy (unsigned char row, unsigned char col) {
	if((row < 4) && (col < 0x10)) {
		switch (row) {
			case 0: lcdgotoaddr(LCD0OFFSET + col); break;
			case 1: lcdgotoaddr(LCD1OFFSET + col); break;
			case 2: lcdgotoaddr(LCD2OFFSET + col); break;
			case 3: lcdgotoaddr(LCD3OFFSET + col); break;
			default: lcdgotoaddr(LCDHOME);
		} //switch
	} //sanity
}

/*=============================================*/

void lcdputch (char ch) {

	wr_lcdDat(ch);
}

/*=============================================*/

void lcdputstr (char *string) {					 	// Write the 2 line message to LCD

  int i;

  for (i=0; i<=strlen(string)-1; ++i)
   {
    if (i == 16)
       wr_lcdReg(LCDHOME | LCD1OFFSET);
    if (i == 32)
       wr_lcdReg(LCDHOME | LCD2OFFSET);
    if (i == 48)
	   wr_lcdReg(LCDHOME | LCD3OFFSET);
	if (i == 64)
	   wr_lcdReg(LCDHOME | LCD0OFFSET);
	lcdputch(string[i]);
   }
}

/*==============================================*/

void clrLcd () {

	wr_lcdReg(0x01); 									//-- clear LCD display
	wr_lcdReg(0x80); 									//-- cursor go to 0x00
	delay_millisec(5);
}

/*=============================================*/
